#include <pcap.h>
#include <pthread.h>
#include "udp_listen.h"
#include "prism.h"
#include "liste.h"
#include "timer_cleaner.h"


struct ieee80211_header
{
  u_short frame_control;
  u_short frame_duration;
  u_char recipient[6];
  u_char source_addr[6];
  u_char address3[6];
  u_short sequence_control;
  u_char address4[6];
};

void* pcap() {
    char errbuf[1600] ;
    pcap_t * handle = NULL;
    struct prism_header *ph;
    struct ieee80211_header * eh;
    struct pcap_pkthdr header;
    const u_char * packet;
    //struct timeval previous;
    //struct timeval current;


    handle = pcap_open_live("prism0", 1600, 1, 1000, errbuf);
    if ( handle == NULL ) {
      printf("Could not open pcap on interface\n");

    }
    //gettimeofday(&previous, NULL);
    while ( 1 ) {
        packet = pcap_next(handle, &header);
        if ( ((unsigned int *) packet)[0] == 0x41 ) {
            ph = (struct prism_header *) packet;
            eh = (struct ieee80211_header *) (packet + ph->msglen);
            // Check if FromDS flag equals 0
            if ( (eh->frame_control & 0xc0) == 0x80 ) {
                /* Do something with (ph->rssi).data */
                //printf("%d\n",(ph->rssi).data);
                sem_wait(&list_protect);
                DeviceList * tmp = getByMAC(dl, eh->source_addr);
                sem_post(&list_protect);
                if (tmp == NULL) {
                    sem_wait(&list_protect);
                    add_device(&dl, eh->source_addr);
                    sem_post(&list_protect);
                    tmp = dl;
                }
                sem_wait(&list_protect);
                add_rssi_sample(tmp, (ph->rssi).data);  
                sem_post(&list_protect);
            }
        }
        //gettimeofday(&current, NULL);
        /*printf("%ld %ld %ld %ld %ld\n", current.tv_sec, current.tv_usec, previous.tv_sec, 
          previous.tv_usec, (current.tv_sec * 1000000 + current.tv_usec) - (previous.tv_sec * 1000000 
          + previous.tv_usec));*/
        /*if ((current.tv_sec * 1000000 + current.tv_usec) - (previous.tv_sec * 1000000 
                    + previous.tv_usec) > 1000000) {
            sem_wait(&list_protect);
            delete_outdated(dl, current);
            sem_post(&list_protect);
            sem_wait(&list_protect);
            print_lists(dl);
            printf("\n\n");
            sem_post(&list_protect);
            gettimeofday(&previous, NULL);
        }*/
    }
    pcap_close ( handle );
    print_lists(dl);
    return NULL;
}
int main() {
    pthread_t pcap_thread;
    pthread_t udp_thread;
    pthread_t timer_thread;

    sem_init(&list_protect, 0, 1);

    pthread_create ( &pcap_thread, NULL, pcap, NULL);
    pthread_create ( &udp_thread, NULL, listen_udp, NULL);
    pthread_create ( &timer_thread, NULL, cleaner, NULL);
    pthread_join ( pcap_thread, NULL);
    pthread_join ( udp_thread, NULL);
    pthread_join ( timer_thread, NULL);
    return 0;
}
